home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / x / volume2 / emacs.vms / patch1 next >
Encoding:
Internet Message Format  |  1988-12-12  |  56.0 KB

  1. Path: uunet!wyse!mikew
  2. From: mikew@wyse.wyse.com (Mike Wexler)
  3. Newsgroups: comp.sources.x
  4. Subject: v02i042:  Gnu emacs for X/VMS, Patch1
  5. Message-ID: <1895@wyse.wyse.com>
  6. Date: 12 Dec 88 17:38:33 GMT
  7. Organization: Wyse Technology, San Jose
  8. Lines: 1850
  9. Approved: mikew@wyse.com
  10.  
  11. Submitted-by: Joshua Marantz <josh@vx.lcs.mit.edu>
  12. Posting-number: Volume 2, Issue 42
  13. Archive-name: emacs.vms/patch1
  14.  
  15.  
  16. I think that enough people were interested in VMS X11 Gnu Emacs to justify
  17. distribution.  I have given Nelson Beebe full sources to be distributed
  18. from CC.UTAH.EDU.  He may make some announcement about that.  The unix
  19. context diffs, and a vms-compatible version of direx.el are listed below.
  20.  
  21. Make sure you run vms-pp on the unix 18.52 sources before you patch them
  22. with my diffs.  To patch in unix, set up a subdirectory "vmssrc" with
  23. the vms-pp'd unix sources in them, and type "patch -p <vmsemacs.dif".
  24. On VMS, you may be able to apply these patches by hand.  It would be
  25. easier to obtain the full sources (which are a 120k compressed tar file)
  26. from utah.  Other sources (such as the Vax SIG tape) may distribute it
  27. as well.  If anyone wants the full sources mailed directly to them, let
  28. me know.
  29.  
  30. Direx.el is Thomas Lord's (tbl@k.cs.cmu.edu) package for directory editing
  31. without using a subprocess.  It has much of the functionality of dired.
  32. I hacked it to work on VMS.  I suspect that it should still work on Unix,
  33. but I haven't tried it.  I admit I didn't do a very complete job on this,
  34. but it works for all the functions that I use.
  35.  
  36. Good luck.
  37.  
  38. ----------------------Paste into file vmsemacs.dif------------------------
  39. *** unixsrc/dired.c    Tue Dec  6 14:53:13 1988
  40. --- vmssrc/dired.c    Mon Nov 28 15:23:35 1988
  41. ***************
  42. *** 363,368 ****
  43. --- 363,387 ----
  44.           Fcons (make_number (time & 0177777), Qnil));
  45.   }
  46.   
  47. + /* --------Added by Joshua Marantz, Viewlogic Systems Inc, 11/1/88-------- */
  48. + DEFUN ("time-string", Ftime_string, Stime_string, 1, 1, 0,
  49. +   "Convert TIME-LIST, which is a list of the high-order and\n\
  50. + low-order bytes of a Unix time value, to a string.")
  51. +   (time_list)
  52. +     Lisp_Object time_list;
  53. + {
  54. +     Lisp_Object s;
  55. +     long time_val, high, low;
  56. +     char *temp;
  57. +     s = Fcar (time_list);           CHECK_NUMBER (s, 3);  high = XFASTINT (s);
  58. +     s = Fcar (Fcdr (time_list));    CHECK_NUMBER (s, 3);  low =  XFASTINT (s);
  59. +     time_val = (high << 16) | low;
  60. +     temp = (char *) ctime (&time_val);
  61. +     return (build_string (temp));
  62. + }
  63.   DEFUN ("file-attributes", Ffile_attributes, Sfile_attributes, 1, 1, 0,
  64.     "Return a list of attributes of file FILENAME.\n\
  65.   Value is nil if specified file cannot be opened.\n\
  66. ***************
  67. *** 445,450 ****
  68. --- 464,472 ----
  69.   #endif /* VMS */
  70.     defsubr (&Sfile_name_all_completions);
  71.     defsubr (&Sfile_attributes);
  72. + /* --------Added by Joshua Marantz, Viewlogic Systems Inc, 11/1/88-------- */
  73. +   defsubr (&Stime_string);
  74.   
  75.   #ifdef VMS
  76.     Qcompletion_ignore_case = intern ("completion-ignore-case");
  77. *** unixsrc/keyboard.c    Tue Dec  6 14:53:18 1988
  78. --- vmssrc/keyboard.c    Mon Nov 28 15:23:35 1988
  79. ***************
  80. *** 992,997 ****
  81. --- 992,1005 ----
  82.        int *addr;
  83.   {
  84.   #ifdef VMS
  85. + /* --------Added by Joshua Marantz, Viewlogic Systems Inc, 11/1/88-------- */
  86. + #ifdef HAVE_X_WINDOWS
  87. +     extern int XTclear_screen ();
  88. +     if (clear_screen_hook == XTclear_screen)
  89. +         XTprocess_window_events ();
  90. + #endif
  91.     /* On VMS, we always have something in the buffer
  92.        if any input is available.  */
  93.     /*** It might be simpler to make interrupt_input 1 on VMS ***/
  94. *** unixsrc/sysdep.c    Tue Dec  6 14:53:25 1988
  95. --- vmssrc/sysdep.c    Mon Nov 28 15:23:36 1988
  96. ***************
  97. *** 19,24 ****
  98. --- 19,36 ----
  99.   and this notice must be preserved on all copies.  */
  100.   
  101.   
  102. + /*
  103. + This file has been heavily modified so that it can work under X11 and
  104. + VMS (using DECwindows).  All the changes conditionalize various things
  105. + between the terminal and DECwindows, using the preprocessor macro
  106. + VMS_X11.  Search for that and you will find all the changes.
  107. +                     Joshua Marantz
  108. +                     Viewlogic Systems, Inc.
  109. +                     (508) 480-0881
  110. +                     josh@vx.lcs.mit.edu
  111. + */
  112.   #include <signal.h>
  113.   #include <setjmp.h>
  114.   
  115. ***************
  116. *** 85,92 ****
  117.   #include <rab.h>
  118.   #endif
  119.   #define    MAXIOSIZE ( 32 * PAGESIZE )    /* Don't I/O more than 32 blocks at a time */
  120. - #endif /* VMS */
  121.   
  122.   #ifndef BSD4_1
  123.   #ifdef BSD /* this is done this way to avoid defined(BSD) || defined (USG)
  124.             because the vms compiler doesn't grok `defined' */
  125. --- 97,128 ----
  126.   #include <rab.h>
  127.   #endif
  128.   #define    MAXIOSIZE ( 32 * PAGESIZE )    /* Don't I/O more than 32 blocks at a time */
  129.   
  130. + /* ---------------------Preprocessor black magic!!----------------------------
  131. +    Define a macro that will perform some action if we are currently running
  132. +    under X11 on VMS.  The critical thing is that the action must not be
  133. +    compiled in unless Emacs is compiled for VMS/X windows, because other
  134. +    VMS users may not be able to link against the DECwindows libraries.
  135. +    On the other hand, just because you've compiled for X windows on VMS
  136. +    doesn't mean you are running it that way on every invocation.  So if
  137. +    we are compiling for X, we use a real if statement, leaving the else
  138. +    clause free.  If we are not, then we do not even reference the action.
  139. +                 -Joshua Marantz,
  140. +         Viewlogic Systems Inc.
  141. +         11/1/88
  142. + */
  143. + #ifdef HAVE_X_WINDOWS
  144. + extern int XTclear_screen ();
  145. + #define IF_VMS_X11(action) if (clear_screen_hook == XTclear_screen) action
  146. + #define IF_NOT_VMS_X11() if (clear_screen_hook != XTclear_screen)
  147. + #else
  148. + #define IF_VMS_X11(action) if (0)
  149. + #define IF_NOT_VMS_X11()
  150. + #endif
  151. + #else /* VMS */
  152. + #endif /* not VMS */
  153.   #ifndef BSD4_1
  154.   #ifdef BSD /* this is done this way to avoid defined(BSD) || defined (USG)
  155.             because the vms compiler doesn't grok `defined' */
  156. ***************
  157. *** 265,274 ****
  158.       return;
  159.   
  160.   #ifdef VMS
  161. !   end_kbd_input ();
  162. !   SYS$QIOW (0, input_chan, IO$_READVBLK|IO$M_PURGE, input_iosb, 0, 0,
  163. !         &buf, 0, 0, terminator_mask, 0, 0);
  164. !   queue_kbd_input ();
  165.   #else /* not VMS */
  166.     ioctl (0, TIOCGETP, &buf);
  167.     ioctl (0, TIOCSETP, &buf);
  168. --- 301,313 ----
  169.       return;
  170.   
  171.   #ifdef VMS
  172. !   IF_VMS_X11 (XTdiscard_input ());
  173. !   else {
  174. !       end_kbd_input ();
  175. !       SYS$QIOW (0, input_chan, IO$_READVBLK|IO$M_PURGE, input_iosb, 0, 0,
  176. !         &buf, 0, 0, terminator_mask, 0, 0);
  177. !       queue_kbd_input ();
  178. !   }
  179.   #else /* not VMS */
  180.     ioctl (0, TIOCGETP, &buf);
  181.     ioctl (0, TIOCSETP, &buf);
  182. ***************
  183. *** 299,306 ****
  184.     else
  185.       {
  186.   #ifdef VMS
  187. !       SYS$QIOW (0, input_chan, IO$_SENSEMODE, &sg, 0, 0,
  188. !         &sg.class, 12, 0, 0, 0, 0 );
  189.   #else
  190.         SETOSPEED (sg, B9600);
  191.         ioctl (0, TIOCGETP, &sg);
  192. --- 338,346 ----
  193.     else
  194.       {
  195.   #ifdef VMS
  196. !     IF_NOT_VMS_X11 ()
  197. !         SYS$QIOW (0, input_chan, IO$_SENSEMODE, &sg, 0, 0,
  198. !               &sg.class, 12, 0, 0, 0, 0 );
  199.   #else
  200.         SETOSPEED (sg, B9600);
  201.         ioctl (0, TIOCGETP, &sg);
  202. ***************
  203. *** 509,514 ****
  204. --- 549,555 ----
  205.   #ifdef VMS
  206.     unsigned long parent_id;
  207.   
  208. +   IF_VMS_X11 (return (-1));
  209.     parent_id = getppid ();
  210.     if (parent_id && parent_id != 0xffffffff)
  211.       {
  212. ***************
  213. *** 744,751 ****
  214.       ((unsigned) 1 << (process_ef % 32));
  215.     timer_eflist = ((unsigned) 1 << (input_ef % 32)) |
  216.       ((unsigned) 1 << (timer_ef % 32));
  217. !   SYS$QIOW (0, input_chan, IO$_SENSEMODE, &old_gtty, 0, 0,
  218. !         &old_gtty.class, 12, 0, 0, 0, 0);
  219.   #ifndef VMS4_4
  220.     sys_access_reinit ();
  221.   #endif
  222. --- 785,794 ----
  223.       ((unsigned) 1 << (process_ef % 32));
  224.     timer_eflist = ((unsigned) 1 << (input_ef % 32)) |
  225.       ((unsigned) 1 << (timer_ef % 32));
  226. !   IF_VMS_X11 (XTinit_vms_input (input_ef));
  227. !   else
  228. !       SYS$QIOW (0, input_chan, IO$_SENSEMODE, &old_gtty, 0, 0,
  229. !         &old_gtty.class, 12, 0, 0, 0, 0);
  230.   #ifndef VMS4_4
  231.     sys_access_reinit ();
  232.   #endif
  233. ***************
  234. *** 811,818 ****
  235.   #endif /* not HAVE_TERMIO */
  236.   
  237.   #ifdef VMS
  238. !       SYS$QIOW (0, input_chan, IO$_SETMODE, &input_iosb, 0, 0,
  239. !         &sg.class, 12, 0, 0, 0, 0);
  240.   #else
  241.         ioctl (0, TIOCSETN, &sg);
  242.   #endif /* not VMS */
  243. --- 854,862 ----
  244.   #endif /* not HAVE_TERMIO */
  245.   
  246.   #ifdef VMS
  247. !       IF_NOT_VMS_X11 ()
  248. !       SYS$QIOW (0, input_chan, IO$_SETMODE, &input_iosb, 0, 0,
  249. !             &sg.class, 12, 0, 0, 0, 0);
  250.   #else
  251.         ioctl (0, TIOCSETN, &sg);
  252.   #endif /* not VMS */
  253. ***************
  254. *** 885,891 ****
  255.         SYS$QIOW (0, input_chan, IO$_SETMODE|IO$M_OUTBAND, 0, 0, 0,
  256.           interrupt_signal, oob_chars, 0, 0, 0, 0);
  257.   */
  258. !       queue_kbd_input (0);
  259.   #endif /* VMS */
  260.       }
  261.   #ifdef VMS  /* VMS sometimes has this symbol but lacks setvbuf.  */
  262. --- 929,936 ----
  263.         SYS$QIOW (0, input_chan, IO$_SETMODE|IO$M_OUTBAND, 0, 0, 0,
  264.           interrupt_signal, oob_chars, 0, 0, 0, 0);
  265.   */
  266. !       IF_NOT_VMS_X11 ()
  267. !       queue_kbd_input (0);
  268.   #endif /* VMS */
  269.       }
  270.   #ifdef VMS  /* VMS sometimes has this symbol but lacks setvbuf.  */
  271. ***************
  272. *** 921,926 ****
  273. --- 966,972 ----
  274.     if (noninteractive)
  275.       return 1;
  276.   #ifdef VMS
  277. +   IF_VMS_X11 (return (1));
  278.     SYS$QIOW (0, input_chan, IO$_SENSEMODE, &sg, 0, 0,
  279.           &sg.class, 12, 0, 0, 0, 0);
  280.   #else
  281. ***************
  282. *** 962,971 ****
  283.   #else /* not TIOCGWNSIZ */
  284.   #ifdef VMS
  285.     TERMINAL sg;
  286. !   SYS$QIOW (0, input_chan, IO$_SENSEMODE, &sg, 0, 0,
  287. !         &sg.class, 12, 0, 0, 0, 0);
  288. !   *widthp = sg.scr_wid;
  289. !   *heightp = sg.scr_len;
  290.   #else /* system doesn't know size */
  291.     *widthp = 0;
  292.     *heightp = 0;
  293. --- 1008,1020 ----
  294.   #else /* not TIOCGWNSIZ */
  295.   #ifdef VMS
  296.     TERMINAL sg;
  297. !   IF_VMS_X11 (*widthp = *heightp = 0);
  298. !   else {
  299. !       SYS$QIOW (0, input_chan, IO$_SENSEMODE, &sg, 0, 0,
  300. !         &sg.class, 12, 0, 0, 0, 0);
  301. !       *widthp = sg.scr_wid;
  302. !       *heightp = sg.scr_len;
  303. !   }
  304.   #else /* system doesn't know size */
  305.     *widthp = 0;
  306.     *heightp = 0;
  307. ***************
  308. *** 1019,1027 ****
  309.       reset_sigio ();
  310.   #endif /* BSD4_1 */
  311.   #ifdef VMS
  312. !   end_kbd_input ();
  313. !   SYS$QIOW (0, input_chan, IO$_SETMODE, &input_iosb, 0, 0,
  314. !         &old_gtty.class, 12, 0, 0, 0, 0);
  315.   #else /* not VMS */
  316.     while (ioctl (0, TCSETAW, &old_gtty) < 0 && errno == EINTR);
  317.   #endif /* not VMS */
  318. --- 1068,1078 ----
  319.       reset_sigio ();
  320.   #endif /* BSD4_1 */
  321.   #ifdef VMS
  322. !   IF_NOT_VMS_X11 () {
  323. !       end_kbd_input ();
  324. !       SYS$QIOW (0, input_chan, IO$_SETMODE, &input_iosb, 0, 0,
  325. !         &old_gtty.class, 12, 0, 0, 0, 0);
  326. !   }
  327.   #else /* not VMS */
  328.     while (ioctl (0, TCSETAW, &old_gtty) < 0 && errno == EINTR);
  329.   #endif /* not VMS */
  330. ***************
  331. *** 1035,1052 ****
  332.   
  333.   /* Assigning an input channel is done at the start of Emacs execution.
  334.      This is called each time Emacs is resumed, also, but does nothing
  335. !    because input_chain is no longer zero.  */
  336.   
  337.   init_vms_input()
  338.   {
  339.     int status;
  340.     
  341. !   if (input_chan == 0)
  342. !     {
  343. !       status = SYS$ASSIGN (&input_dsc, &input_chan, 0, 0);
  344. !       if (! (status & 1))
  345. !     LIB$STOP (status);
  346. !     }
  347.   }
  348.   
  349.   /* Deassigning the input channel is done before exiting.  */
  350. --- 1086,1104 ----
  351.   
  352.   /* Assigning an input channel is done at the start of Emacs execution.
  353.      This is called each time Emacs is resumed, also, but does nothing
  354. !    because input_chan is no longer zero.  */
  355.   
  356.   init_vms_input()
  357.   {
  358.     int status;
  359.     
  360. !   if (input_chan == 0) {
  361. !       IF_NOT_VMS_X11 () {
  362. !       status = SYS$ASSIGN (&input_dsc, &input_chan, 0, 0);
  363. !       if (! (status & 1))
  364. !           LIB$STOP (status);
  365. !       }
  366. !   }
  367.   }
  368.   
  369.   /* Deassigning the input channel is done before exiting.  */
  370. ***************
  371. *** 1053,1059 ****
  372.   
  373.   stop_vms_input ()
  374.   {
  375. !   return SYS$DASSGN (input_chan);
  376.   }
  377.   
  378.   short input_buffer;
  379. --- 1105,1112 ----
  380.   
  381.   stop_vms_input ()
  382.   {
  383. !     IF_NOT_VMS_X11 ()
  384. !     return SYS$DASSGN (input_chan);
  385.   }
  386.   
  387.   short input_buffer;
  388. ***************
  389. *** 1115,1154 ****
  390.   
  391.   /* Wait until there is something in kbd_buffer.  */
  392.   
  393. ! wait_for_kbd_input ()
  394. ! {
  395. !   extern int have_process_input, process_exited;
  396.   
  397. !   /* If already something, avoid doing system calls.  */
  398. !   if (detect_input_pending ())
  399. !     {
  400. !       return;
  401. !     }
  402. !   /* Clear a flag, and tell ast routine above to set it.  */
  403. !   SYS$CLREF (input_ef);
  404. !   waiting_for_ast = 1;
  405. !   /* Check for timing error: ast happened while we were doing that.  */
  406. !   if (!detect_input_pending ())
  407. !     {
  408. !       /* No timing error: wait for flag to be set.  */
  409. !       SYS$WFLOR (input_ef, input_eflist);
  410. !       if (!detect_input_pending ())
  411. !     /* Check for subprocess input availability */
  412. !     {
  413. !       int dsp = have_process_input || process_exited;
  414.   
  415. !       if (have_process_input)
  416. !         process_command_input ();
  417. !       if (process_exited)
  418. !         process_exit ();
  419. !       if (dsp)
  420. !         {
  421. !           RedoModes++;
  422. !           DoDsp (1);
  423.           }
  424.       }
  425.       }
  426. -   waiting_for_ast = 0;
  427.   }
  428.   
  429.   /* Get rid of any pending QIO, when we are about to suspend
  430. --- 1168,1212 ----
  431.   
  432.   /* Wait until there is something in kbd_buffer.  */
  433.   
  434. ! /* --------Added by Joshua Marantz, Viewlogic Systems Inc, 11/1/88--------
  435. !    This routine was changed to use a while loop so that X11 window events,
  436. !    such as exposure and resizing, would be handled better.  Under the old
  437. !    method, which used an "if" instead of a "while", window events would
  438. !    not be handled until the next keyboard event.
  439. ! */
  440. ! wait_for_kbd_input () {
  441. !     extern int have_process_input, process_exited;
  442.   
  443. !     /* If already something, avoid doing system calls.  */
  444. !     while (!detect_input_pending ()) {
  445.   
  446. !     /* Clear a flag, and tell ast routine above to set it.  */
  447. !     SYS$CLREF (input_ef);
  448. !     waiting_for_ast = 1;
  449. !     /* Check for timing error: ast happened while we were doing that.  */
  450. !     if (!detect_input_pending ()) {
  451. !         /* No timing error: wait for flag to be set.  */
  452. !         SYS$WFLOR (input_ef, input_eflist);
  453. !         if (!detect_input_pending ()) {
  454. !         /* Check for subprocess input availability */
  455. !         int dsp = have_process_input || process_exited;
  456. !         if (have_process_input)
  457. !             process_command_input ();
  458. !         if (process_exited)
  459. !             process_exit ();
  460. !         if (dsp) {
  461. !             RedoModes++;
  462. !             DoDsp (1);
  463. !         }
  464. !         IF_VMS_X11 (XTprocess_window_events ());
  465.           }
  466.       }
  467. +     waiting_for_ast = 0;
  468.       }
  469.   }
  470.   
  471.   /* Get rid of any pending QIO, when we are about to suspend
  472. ***************
  473. *** 2737,2742 ****
  474. --- 2795,2801 ----
  475.     return pathname;
  476.   }
  477.   
  478. + #ifndef VMS5_0
  479.   getppid ()
  480.   {
  481.     long item_code = JPI$_OWNER;
  482. ***************
  483. *** 2751,2756 ****
  484. --- 2810,2816 ----
  485.       }
  486.     return parent_id;
  487.   }
  488. + #endif
  489.   
  490.   #ifdef getuid
  491.   #undef getuid
  492. *** unixsrc/x11fns.c    Tue Dec  6 14:53:28 1988
  493. --- vmssrc/x11fns.c    Mon Nov 28 15:23:36 1988
  494. ***************
  495. *** 40,46 ****
  496.   #else
  497.   #include <sys/time.h>
  498.   #endif
  499. ! #include <fcntl.h>
  500.   #include <setjmp.h>
  501.   
  502.   #ifdef HAVE_X_WINDOWS
  503. --- 40,46 ----
  504.   #else
  505.   #include <sys/time.h>
  506.   #endif
  507. ! /* #include <fcntl.h> --------Commented out 11/1/88, Joshua Marantz--------*/
  508.   #include <setjmp.h>
  509.   
  510.   #ifdef HAVE_X_WINDOWS
  511. *** unixsrc/x11term.c    Tue Dec  6 14:53:32 1988
  512. --- vmssrc/x11term.c    Mon Nov 28 15:23:37 1988
  513. ***************
  514. *** 21,27 ****
  515. --- 21,53 ----
  516.   /* Written by Yakim Martillo, mods and things by Robert Krawitz  */
  517.   /* Redone for X11 by Robert French */
  518.   /* Thanks to Mark Biggers for all of the Window Manager support */
  519. + /*
  520.   
  521. + Heavily #ifdefd to support VAX/VMS.  A better X11 implementation would
  522. + have been portable between operating systems.  Unfortunately, the
  523. + original Unix implementation depends too much on Unix signals to
  524. + implement detection of Control-G interrupts and window events.  The
  525. + easiest way to get this to work under VMS was to use the DECwindows
  526. + asynchronous event notification support to hook into the existing AST
  527. + support for terminal I/O.  The same event flag is used, and it appears
  528. + to work well.  The cost is portability between X on different
  529. + operating systems.  The benefits on VMS, however, are many: The screen
  530. + refresh speed much greater than that in a terminal emulator window.
  531. + The Compose key functions as a Meta key.  And you can resize an Emacs
  532. + in progress, without having to suspend and resume.  Another difference
  533. + between VMS and Unix is that the DECwindows window manager supports
  534. + focus-based (click-to-type) keyboard management, and so the
  535. + solid/hollow cursor is based on focus notification instead of
  536. + enter/leave events.
  537. + Look for #ifdef/#ifndef VMS to spot all the differences.
  538. +                     Joshua Marantz
  539. +                     Viewlogic Systems, Inc.
  540. +                     (508) 480-0881
  541. +                     josh@vx.lcs.mit.edu
  542. + */
  543.   /*
  544.    *    $Source: /mit/emacs/src/RCS/11xterm.c,v $
  545.    *    $Author: rfrench $
  546. ***************
  547. *** 82,88 ****
  548.   #include <sys/time.h>
  549.   #endif
  550.   
  551. ! #include <fcntl.h>
  552.   #include <stdio.h>
  553.   #include <ctype.h>
  554.   #include <errno.h>
  555. --- 108,114 ----
  556.   #include <sys/time.h>
  557.   #endif
  558.   
  559. ! /* #include <fcntl.h> */
  560.   #include <stdio.h>
  561.   #include <ctype.h>
  562.   #include <errno.h>
  563. ***************
  564. *** 609,615 ****
  565. --- 635,643 ----
  566.   XTflash ()
  567.   {
  568.       XGCValues gcv_temp;
  569. + #ifndef VMS
  570.       struct timeval to;
  571. + #endif
  572.       BLOCK_INPUT_DECLARE ();
  573.   
  574.   #ifdef XDEBUG
  575. ***************
  576. *** 627,640 ****
  577.                  screen_height*XXfonth+2*XXInternalBorder);
  578.       XFlush (XXdisplay);
  579.   
  580.       UNBLOCK_INPUT ();
  581.       to.tv_sec = 0;
  582.       to.tv_usec = 250000;
  583. -     
  584.       select(0, 0, 0, 0, &to);
  585.       
  586.       BLOCK_INPUT ();
  587.   
  588.       XFillRectangle (XXdisplay, XXwindow, XXgc_temp, 0, 0,
  589.               screen_width*XXfontw+2*XXInternalBorder,
  590. --- 655,672 ----
  591.                  screen_height*XXfonth+2*XXInternalBorder);
  592.       XFlush (XXdisplay);
  593.   
  594. + #ifdef VMS
  595. +     /* this routine really should have better granularity so we can
  596. +        do .25 seconds just like the big boys from Unix can! */
  597. +     input_wait_timeout (1);
  598. + #else
  599.       UNBLOCK_INPUT ();
  600.       to.tv_sec = 0;
  601.       to.tv_usec = 250000;
  602.       select(0, 0, 0, 0, &to);
  603.       
  604.       BLOCK_INPUT ();
  605. + #endif
  606.   
  607.       XFillRectangle (XXdisplay, XXwindow, XXgc_temp, 0, 0,
  608.               screen_width*XXfontw+2*XXInternalBorder,
  609. ***************
  610. *** 1039,1044 ****
  611. --- 1071,1077 ----
  612.       }
  613.   }
  614.       
  615. + #ifndef VMS
  616.   /* Substitutes for standard read routine.  Under X not interested in individual
  617.    * bytes but rather individual packets.
  618.    */
  619. ***************
  620. *** 1054,1059 ****
  621. --- 1087,1093 ----
  622.   
  623.       return (internal_socket_read (bufp, numchars));
  624.   }
  625. + #endif /* not VMS */
  626.   
  627.   /*
  628.    * Interpreting incoming keycodes. Should have table modifiable as needed
  629. ***************
  630. *** 1211,1216 ****
  631. --- 1245,1251 ----
  632.   }
  633.   #endif /* not sun */
  634.       
  635. + #ifndef VMS
  636.   internal_socket_read(bufp, numchars)
  637.       register unsigned char *bufp;
  638.       register int numchars;
  639. ***************
  640. *** 1399,1404 ****
  641. --- 1434,1440 ----
  642.     UNBLOCK_INPUT ();
  643.     return count;
  644.   }
  645. + #endif /* not VMS */
  646.   
  647.   /* Exit gracefully from gnuemacs, doing an autosave and giving a status.
  648.    */
  649. ***************
  650. *** 1416,1421 ****
  651. --- 1452,1458 ----
  652.   
  653.   xfixscreen ()
  654.   {
  655. + #ifndef VMS
  656.       BLOCK_INPUT_DECLARE ();
  657.   
  658.       /* Yes, this is really what I mean -- Check to see if we've
  659. ***************
  660. *** 1432,1437 ****
  661. --- 1469,1475 ----
  662.           CursorToggle ();
  663.   
  664.       UNBLOCK_INPUT ();
  665. + #endif
  666.   }
  667.       
  668.   
  669. ***************
  670. *** 1538,1544 ****
  671. --- 1576,1584 ----
  672.       update_begin_hook = XTupdate_begin;
  673.       update_end_hook = XTupdate_end;
  674.       set_terminal_window_hook = XTset_terminal_window;
  675. + #ifndef VMS
  676.       read_socket_hook = XTread_socket;
  677. + #endif
  678.       topos_hook = XTtopos;
  679.       reassert_line_highlight_hook = XTreassert_line_highlight;
  680.       scroll_region_ok = 1;    /* we'll scroll partial screens */
  681. ***************
  682. *** 1575,1583 ****
  683. --- 1615,1637 ----
  684.       XXicon_usebitmap = 0;
  685.       
  686.       temp_font = "fixed";
  687. + /* ------Joshua Marantz 11/1/88, argv[0] on VMS contains full pathname------*/
  688. + #ifdef VMS
  689.       progname = xargv[0];
  690. +     if (ptr = rindex(progname, ']'))
  691. +       progname = ptr+1;
  692. +     ptr = progname;
  693. +     progname = xmalloc (strlen (ptr) + 1);
  694. +     strcpy (progname, ptr);
  695. +     if (ptr = rindex (progname, '.'))
  696. +         *ptr = 0;
  697. + #else
  698. +     progname = xargv[0];
  699.       if (ptr = rindex(progname, '/'))
  700.         progname = ptr+1;
  701. + #endif
  702.       XXpid = getpid ();
  703.       default_window = "=80x24+0+0";
  704.   
  705. ***************
  706. *** 2056,2061 ****
  707. --- 2110,2131 ----
  708.   }
  709.   
  710.   
  711. + #ifdef VMS
  712. + static void gethostname(buf, len)
  713. +     char *buf;
  714. +     int len;
  715. + {
  716. +     char *s;
  717. +     s = getenv ("SYS$NODE");
  718. +     if (s == NULL)
  719. +         buf[0] = '\0';
  720. +     else {
  721. +         strncpy (buf, s, len - 2);
  722. +         buf[len - 1] = '\0';
  723. +     } /* else */
  724. + } /* static void gethostname */
  725. + #endif
  726.   /* ------------------------------------------------------------
  727.    */
  728.   static char  hostname[100];
  729. ***************
  730. *** 2356,2367 ****
  731.   
  732.       XSelectInput(XXdisplay, XXwindow, KeyPressMask |
  733.            ExposureMask | ButtonPressMask | ButtonReleaseMask |
  734. !          EnterWindowMask | LeaveWindowMask |
  735.            StructureNotifyMask);
  736.   
  737.       XMapWindow (XXdisplay, XXwindow);
  738.       XFlush (XXdisplay);
  739.   }
  740.   
  741.   #endif /* HAVE_X_WINDOWS */
  742.   
  743. --- 2426,2614 ----
  744.   
  745.       XSelectInput(XXdisplay, XXwindow, KeyPressMask |
  746.            ExposureMask | ButtonPressMask | ButtonReleaseMask |
  747. !          EnterWindowMask | LeaveWindowMask | FocusChangeMask |
  748.            StructureNotifyMask);
  749.   
  750.       XMapWindow (XXdisplay, XXwindow);
  751.       XFlush (XXdisplay);
  752.   }
  753. + #ifdef VMS
  754. + /* The VMS routines in SYSDEP.C use event flags to determine if the user
  755. +    hit the key during a timer run.  Fortunately, DECwindows supplies AST
  756. +    notification capability to X events, so we can set the AST that way. */
  757. + extern int waiting_for_ast;
  758. + static int input_ast(input_ef)
  759. +     int input_ef;
  760. + {
  761. +     XEvent event;
  762. +     int nbytes, i;
  763. +     char mapping_buf[20];
  764. +     KeySym keysym;
  765. +     XComposeStatus status;
  766. +     if (waiting_for_ast)
  767. +     SYS$SETEF (input_ef);
  768. +     waiting_for_ast = 0;
  769. +     while (XCheckMaskEvent (XXdisplay, KeyPressMask | ButtonPressMask |
  770. +                 ButtonReleaseMask, &event))
  771. +     {
  772. +     switch (event.type) {
  773. +       case KeyPress:
  774. +         /* Someday this will be unnecessary as we will
  775. +            be able to use XRebindKeysym so XLookupString
  776. +            will have always give us the string we want. */
  777. +         nbytes = 1;
  778. +         keysym = XKeycodeToKeysym (XXdisplay, event.xkey.keycode, 0);
  779. + #define CTRL(c) (c - 64)
  780. + #define META(c) (c + 128)
  781. + #define STUFF(c) *mapping_buf = c; break;
  782. +         switch (keysym) {
  783. +         case XK_Left:    STUFF (CTRL ('B'));
  784. +         case XK_Right:   STUFF (CTRL ('F'));
  785. +         case XK_Up:      STUFF (CTRL ('P'));
  786. +         case XK_Down:    STUFF (CTRL ('N'));
  787. +         case XK_Prior:   STUFF (META ('V'));
  788. +         case XK_Next:    STUFF (CTRL ('V'));
  789. +         case XK_Insert:  STUFF (CTRL ('Y'));
  790. +         case DXK_Remove: STUFF (CTRL ('W'));
  791. +         case XK_Find:    STUFF (CTRL ('S'));
  792. +         case XK_Select:  STUFF (CTRL ('@'));
  793. +         case XK_Help:    STUFF (CTRL ('H'));
  794. +         case XK_Execute: STUFF (CTRL ('\\'));
  795. +         default:
  796. +             if (IsFunctionKey (keysym) || IsMiscFunctionKey (keysym)) {
  797. +             strcpy (mapping_buf, "[");
  798. +             strcat (mapping_buf, stringFuncVal (keysym));
  799. +             strcat (mapping_buf, "~");
  800. +             nbytes = strlen (mapping_buf);
  801. +             }
  802. +             else
  803. +             nbytes = XLookupString (&event, mapping_buf, 20,
  804. +                         &keysym, &status);
  805. +         } /* switch */
  806. +         if (nbytes > 0) {
  807. +         if (event.xkey.state & Mod1Mask)
  808. +             *mapping_buf |= METABIT;
  809. +         for (i = 0; i < nbytes; i++)
  810. +             kbd_buffer_store_char (mapping_buf[i]);
  811. +         }
  812. +         break;
  813. +       case ButtonPress:
  814. +       case ButtonRelease:
  815. +         kbd_buffer_store_char ('X' & 037);
  816. +         kbd_buffer_store_char ('@' & 037);
  817. +         if (XXm_queue_num == XMOUSEBUFSIZE)
  818. +           break;
  819. +         XXm_queue[XXm_queue_in] = (XEvent *) malloc (sizeof(XEvent));
  820. +         *XXm_queue[XXm_queue_in] = event;
  821. +         XXm_queue_num++;
  822. +         XXm_queue_in = (XXm_queue_in + 1) % XMOUSEBUFSIZE;
  823. +         break;
  824. +     }
  825. +     }
  826. + }
  827. + XTinit_vms_input(input_ef)
  828. +     unsigned long input_ef;
  829. + {
  830. +     XSelectAsyncInput (XXdisplay, XXwindow,
  831. +                        KeyPressMask | ExposureMask | ButtonPressMask |
  832. +                        ButtonReleaseMask | EnterWindowMask |
  833. +                FocusChangeMask |
  834. +                        LeaveWindowMask | StructureNotifyMask,
  835. +                        input_ast, input_ef);
  836. + } /* XTinit_vms_input */
  837. + XTdiscard_input () {
  838. + }
  839. + static void solid_cursor() {
  840. +     CursorToggle ();
  841. +     CursorOutline = 0;
  842. +     CursorToggle ();
  843. + }
  844. + static void hollow_cursor() {
  845. +     CursorToggle ();
  846. +     CursorOutline = 1;
  847. +     CursorToggle ();
  848. + }
  849. + XTprocess_window_events() {
  850. +     int rows, cols;
  851. +     XEvent event;
  852. +     static int focus = 0;
  853. +     while (XCheckMaskEvent (XXdisplay, ExposureMask | EnterWindowMask |
  854. +                 LeaveWindowMask | StructureNotifyMask |
  855. +                 FocusChangeMask, &event))
  856. +     {
  857. +     event.type &= 0177;        /* Mask out XSendEvent indication */
  858. +     switch (event.type) {
  859. +       case NoExpose:
  860. +       default:                                                       break;
  861. +       case MappingNotify:     XRefreshKeyboardMapping(&event);       break;
  862. +       case MapNotify:         WindowMapped = 1;                      break;
  863. +       case UnmapNotify:       WindowMapped = 0;                      break;
  864. +       case EnterNotify:       if (!focus) solid_cursor ();           break;
  865. +       case LeaveNotify:       if (!focus) hollow_cursor ();          break;
  866. +       case FocusIn:           solid_cursor ();  focus = 1;           break;
  867. +       case FocusOut:          hollow_cursor (); focus = 1;           break;
  868. +       case ConfigureNotify:
  869. +         if (abs (pixelheight - event.xconfigure.height) < XXfonth &&
  870. +         abs (pixelwidth  - event.xconfigure.width) <  XXfontw)
  871. +         break;
  872. +         configure_pending = 1;
  873. +         rows = (event.xconfigure.height - 2 * XXInternalBorder) / XXfonth;
  874. +         cols = (event.xconfigure.width  - 2 * XXInternalBorder) / XXfontw;
  875. +         pixelwidth = cols * XXfontw + 2 * XXInternalBorder;
  876. +         pixelheight = rows * XXfonth + 2 * XXInternalBorder;
  877. +         break;
  878. +       case Expose:
  879. +         if (configure_pending) {
  880. +           int width, height;
  881. +           if (event.xexpose.count)
  882. +         break;
  883. +           /* This is absolutely, amazingly gross.
  884. +            * However, without it, emacs will core
  885. +            * dump if the window gets too small.  And
  886. +            * uwm is too brain-damaged to handle
  887. +            * large minimum size windows. */
  888. +           width = (pixelwidth-2*XXInternalBorder)/XXfontw;
  889. +           height = (pixelheight-2*XXInternalBorder)/XXfonth;
  890. +           if (width > 11 && height > 4)
  891. +               change_screen_size (height, width, 0);
  892. +           dumprectangle (0,0,pixelheight,pixelwidth);
  893. +           configure_pending = 0;
  894. +           break;
  895. +         }
  896. +         dumprectangle (event.xexpose.y-XXInternalBorder,
  897. +                event.xexpose.x-XXInternalBorder,
  898. +                event.xexpose.height,
  899. +                event.xexpose.width);
  900. +         break;
  901. +       case GraphicsExpose:
  902. +         dumprectangle (event.xgraphicsexpose.y-XXInternalBorder,
  903. +                event.xgraphicsexpose.x-XXInternalBorder,
  904. +                event.xgraphicsexpose.height,
  905. +                event.xgraphicsexpose.width);
  906. +         break;
  907. +     }
  908. +     }
  909. + }
  910. + #endif /* VMS */
  911.   
  912.   #endif /* HAVE_X_WINDOWS */
  913.   
  914. *** unixsrc/x11term.h    Tue Dec  6 18:30:18 1988
  915. --- vmssrc/x11term.h    Tue Dec  6 18:34:56 1988
  916. ***************
  917. *** 3,9 ****
  918. --- 3,11 ----
  919.   #include <X11/keysym.h>
  920.   #include <X11/cursorfont.h>
  921.   #include <X11/Xutil.h>
  922. + #ifndef VMS /* --- This is not needed - Joshua Marantz, 11/1/88 --- */
  923.   #include <X11/X10.h>
  924. + #endif
  925.   
  926.   #define XMOUSEBUFSIZE 64
  927.   
  928. *** unixsrc/s-vms.h    Tue Dec  6 18:30:25 1988
  929. --- vmssrc/s-vms.h    Mon Nov 28 15:23:40 1988
  930. ***************
  931. *** 140,146 ****
  932.      shared library, define this and remake xmakefile and fileio.c. This allows
  933.      us to ship a guaranteed executable image. */
  934.   
  935. ! /* #define LINK_CRTL_SHARE */
  936.   
  937.   /* Define this if you want to read the file SYS$SYSTEM:SYSUAF.DAT for user
  938.      information.  If you do use this, you must either make SYSUAF.DAT world 
  939. --- 140,146 ----
  940.      shared library, define this and remake xmakefile and fileio.c. This allows
  941.      us to ship a guaranteed executable image. */
  942.   
  943. ! #define LINK_CRTL_SHARE
  944.   
  945.   /* Define this if you want to read the file SYS$SYSTEM:SYSUAF.DAT for user
  946.      information.  If you do use this, you must either make SYSUAF.DAT world 
  947. ***************
  948. *** 223,229 ****
  949.   { 0, 50, 75, 110, 134, 150, 300, 600, 1200, 1800, \
  950.     2000, 2400, 3600, 4800, 7200, 9600, 19200 }
  951.   
  952. ! #define PURESIZE 132000
  953.   
  954.   /* Stdio FILE type has extra indirect on VMS, so must alter this macro.  */
  955.   
  956. --- 223,232 ----
  957.   { 0, 50, 75, 110, 134, 150, 300, 600, 1200, 1800, \
  958.     2000, 2400, 3600, 4800, 7200, 9600, 19200 }
  959.   
  960. ! /* --------Added by Joshua Marantz, Viewlogic Systems Inc, 11/1/88-------- */
  961. ! #define PURESIZE 136000     /* For x windows */
  962. ! /* #define PURESIZE 132000 */
  963.   
  964.   /* Stdio FILE type has extra indirect on VMS, so must alter this macro.  */
  965.   
  966. *** unixsrc/config.h    Tue Dec  6 18:30:08 1988
  967. --- vmssrc/config.h    Mon Nov 28 15:23:39 1988
  968. ***************
  969. *** 24,30 ****
  970.      See the file ../etc/MACHINES for a list of systems and
  971.      the names of the s- files to use for them.
  972.      See s-template.h for documentation on writing s- files.  */
  973. ! #include "s-bsd4-2.h"
  974.   
  975.   /* Include here a m- file that describes the machine and system you use.
  976.      See the file ../etc/MACHINES for a list of machines and
  977. --- 24,30 ----
  978.      See the file ../etc/MACHINES for a list of systems and
  979.      the names of the s- files to use for them.
  980.      See s-template.h for documentation on writing s- files.  */
  981. ! #include "s-vms4-4.h"
  982.   
  983.   /* Include here a m- file that describes the machine and system you use.
  984.      See the file ../etc/MACHINES for a list of machines and
  985. ***************
  986. *** 31,37 ****
  987.      the names of the m- files to use for them.
  988.      See m-template.h for info on what m- files should define.
  989.      */
  990. ! #include "m-sun3.h"
  991.   
  992.   /* Load in the conversion definitions if this system
  993.      needs them and the source file being compiled has not
  994. --- 31,37 ----
  995.      the names of the m- files to use for them.
  996.      See m-template.h for info on what m- files should define.
  997.      */
  998. ! #include "m-vax.h"
  999.   
  1000.   /* Load in the conversion definitions if this system
  1001.      needs them and the source file being compiled has not
  1002. ***************
  1003. *** 57,63 ****
  1004.      This appears to work on some machines that support X
  1005.      and not on others.  */
  1006.   
  1007. ! #define HAVE_X_MENU
  1008.   
  1009.   /* Define `subprocesses' should be defined if you want to
  1010.      have code for asynchronous subprocesses
  1011. --- 57,63 ----
  1012.      This appears to work on some machines that support X
  1013.      and not on others.  */
  1014.   
  1015. ! /* #define HAVE_X_MENU */
  1016.   
  1017.   /* Define `subprocesses' should be defined if you want to
  1018.      have code for asynchronous subprocesses
  1019.  
  1020. *** unixsrc/temacs.opt    Tue Dec  6 20:30:00 1988
  1021. --- vmssrc/temacs.opt    Mon Nov 28 15:24:14 1988
  1022. ***************
  1023. *** 46,51 ****
  1024. --- 46,53 ----
  1025.   tparam.obj,-
  1026.   lastfile.obj,-
  1027.   alloca.obj,-
  1028. + x11term.obj,-
  1029. + x11fns.obj,-
  1030.   malloc.obj
  1031.   collect=non_saved_data,-
  1032.   stdin,-
  1033. ***************
  1034. *** 56,59 ****
  1035.   sys_errlist,-
  1036.   sys_nerr,-
  1037.   environ
  1038. ! sys$library:vaxcrtl/library
  1039. --- 58,62 ----
  1040.   sys_errlist,-
  1041.   sys_nerr,-
  1042.   environ
  1043. ! sys$share:decw$xlibshr/share
  1044. ! sys$library:vaxcrtl/lib
  1045. *** unixsrc/compile.com    Tue Dec  6 20:30:06 1988
  1046. --- vmssrc/compile.com    Tue Dec  6 20:28:11 1988
  1047. ***************
  1048. *** 60,62 ****
  1049. --- 60,64 ----
  1050.   $    @recomp lastfile.c
  1051.   $    @recomp malloc.c
  1052.   $    @recomp alloca.c
  1053. + $    @recomp x11term.c
  1054. + $    @recomp x11fns.c
  1055.  
  1056. ----------------------End of vmsemacs.dif---------------------------------
  1057. -----------------------paste into lisp/direx.el--------------------------------
  1058. ; From: tbl@k.cs.cmu.edu (Thomas Lord)
  1059. ; Newsgroups: comp.emacs
  1060. ; Subject: a dired replacement for GNU
  1061. ; Date: 24 Mar 87 23:41:00 GMT
  1062. ; Organization: Carnegie-Mellon University, CS/RI
  1063. ; Posting-Front-End: GNU Emacs 18.36.5 of Sat Feb 14 1987 on k.cs.cmu.edu (berkeley-unix)
  1064. ; <I came in late...what's all this about a ...line eater?>
  1065. ; Below is Direx.el, my replacement for dired.  Since Direx works without
  1066. ; running ls it should be considerably faster on most systems.  There is a
  1067. ; trade off, however.  By default, direx uses a short style directory
  1068. ; listing.  That is, each file is listed by name only (no size,
  1069. ; protection, owner etc).  To get that extra information you must
  1070. ; explicitly call direx-fake-ls (bound to "l" by default).  
  1071. ; To invoke direx on some directory type M-x direx.  You will be
  1072. ; prompted for the directory name.
  1073. ; Direx mode is a superset of dired mode. In addition to the usual
  1074. ; commands the following exist:
  1075. ; direx-alternate-file : kill the current buffer and find the file
  1076. ; pointed to.  If that file is in fact a directory, then direx it.
  1077. ; This is normally bound to "j".  It is very usefull for bopping up and
  1078. ; down directory trees.
  1079. ; direx-expand-subdirectory : add the contents of a subdirectory to a
  1080. ; direx buffer.  Bound to "s".
  1081. ; direx-fake-ls : use the long listing format.  bound to "l"
  1082. ; There may still be bugs, particularly with features that don't get
  1083. ; much exercize locally (such as direx-clean-directory).  Please mail me
  1084. ; reports of any you find.
  1085. ; If you get to like direx (and I hope you will) you may wish to make
  1086. ; the following bindings:
  1087. ; (global-set-key "\C-x\C-f" 'direx-file)
  1088. ; (global-set-key "\C-x\C-v" 'direx-alternate-file)
  1089. ; (global-set-key "\C-x4f"   'direx-file-other-window)
  1090. ; Have fun!
  1091. ; Thomas Lord
  1092. ;  lord@andrew.cmu.edu            <----- prefered
  1093. ;  tbl@k.cs.cmu.edu
  1094. ; ------ cut here and store in direx.el --------
  1095.  
  1096. ;; DIREX commands for Emacs
  1097. ;; Copyright (C) 1985, 1986 Free Software Foundation, Inc.
  1098.  
  1099. ;; This file is part of GNU Emacs.
  1100.  
  1101. ;; GNU Emacs is distributed in the hope that it will be useful,
  1102. ;; but WITHOUT ANY WARRANTY.  No author or distributor
  1103. ;; accepts responsibility to anyone for the consequences of using it
  1104. ;; or for whether it serves any particular purpose or works at all,
  1105. ;; unless he says so in writing.  Refer to the GNU Emacs General Public
  1106. ;; License for full details.
  1107.  
  1108. ;; Everyone is granted permission to copy, modify and redistribute
  1109. ;; GNU Emacs, but only under the conditions described in the
  1110. ;; GNU Emacs General Public License.   A copy of this license is
  1111. ;; supposed to have been given to you along with GNU Emacs so you
  1112. ;; can know your rights and responsibilities.  It should be in a
  1113. ;; file named COPYING.  Among other things, the copyright notice
  1114. ;; and this notice must be preserved on all copies.
  1115. ;;
  1116. ;;
  1117. ;; TODO
  1118.  
  1119.  
  1120. ;; add sorting : involves changes to direx-show-directory-fast,
  1121. ;;               direx-add-entry, direx-move-to-file-name 
  1122. ;;               direx-before-file-name, direx-file-name,
  1123. ;;               direx-expand-subdirectory, and direx-fake-ls but
  1124. ;;               should be very straight-forward 
  1125. ;; add dates to direx-fake-ls :
  1126. ;;               involves addition of a lisp call to ctime in the 
  1127. ;;               gnu-emacs c source 
  1128. ;;
  1129. ;; add mode changing stuff : very easy.  maybe *i*'ll do it.  
  1130. ;; add better support for expanding subdirectories in situ...like
  1131. ;;               maybe getting rid of expandes subdirectories 
  1132. ;;
  1133. ;; -------Made VMS-portable by Joshua Marantz, Viewlogic Systems Inc, 11/1/88
  1134. ;;  This module depends on the new time-string function, written in C, in
  1135. ;;  dired.c:
  1136. ;;
  1137. ;;DEFUN ("time-string", Ftime_string, Stime_string, 1, 1, 0,
  1138. ;;  "Convert TIME-LIST, which is a list of the high-order and\n\
  1139. ;;low-order bytes of a Unix time value, to a string.")
  1140. ;;  (time_list)
  1141. ;;    Lisp_Object time_list;
  1142. ;;{
  1143. ;;    Lisp_Object s;
  1144. ;;    long time_val, high, low;
  1145. ;;    char *temp;
  1146. ;;
  1147. ;;    s = Fcar (time_list);          CHECK_NUMBER (s, 3);  high = XFASTINT (s);
  1148. ;;    s = Fcar (Fcdr (time_list));   CHECK_NUMBER (s, 3);  low =  XFASTINT (s);
  1149. ;;    time_val = (high << 16) | low;
  1150. ;;    temp = (char *) ctime (&time_val);
  1151. ;;    return (build_string (temp));
  1152. ;;}
  1153. ;;
  1154. ;; Someone should really write a uid-to-uname function for VMS, and should
  1155. ;; write a lisp function to shorten the result of time-string a la unix
  1156. ;; "ls -l".  Essentially, it drops the year if it is this year, and drops
  1157. ;; the hour/minute/second info for other years.
  1158.  
  1159.  
  1160. (defun vms-p () (string= system-type 'vax-vms))
  1161.  
  1162. (defun name-around-point ()
  1163.   "Return the whitespace delimitted text under the point."
  1164.   (save-excursion
  1165.     (buffer-substring (progn (re-search-backward "[ \t^]")
  1166.                  (forward-char 1)
  1167.                  (point))
  1168.               (progn (re-search-forward  "[ \t\n%]")
  1169.                  (forward-char -1)
  1170.                  (point)))))
  1171.  
  1172.  
  1173.  
  1174. (defun repeat (n exp)
  1175.   "N times, eval EXP.  Repeat once if N is nil."
  1176.   (let ( (count (or n 1)) )
  1177.     (while (> count 0)
  1178.       (eval exp)
  1179.       (setq count (1- count)))))
  1180.  
  1181.  
  1182. (defvar direx-use-long-directory nil
  1183.   "*If this is non-nil, direx mode will always use a long directory format.")
  1184.  
  1185. (defvar direx-indicate-directories nil
  1186.   "*If non-nil, short direx listings have % after directory names. (Slower)")
  1187.  
  1188.  
  1189. (defun direx-show-directory-fast (directory &optional prefix)
  1190.   "Insert at the point a brief listing of DIRECTORY."
  1191.   (let* ( (buffer-read-only nil)
  1192.       (prefix (or prefix ""))
  1193.       (expanded-name (directory-file-name (expand-file-name directory)))
  1194.       (attributes    (file-attributes expanded-name)) )
  1195.     (cond ( (stringp (car attributes))
  1196.         (direx-show-directory-fast (car attributes)) )
  1197.       ( (not (car attributes))
  1198.         (error "%s is not a directory!" directory) )
  1199.       ( t
  1200.         (or (bolp)
  1201.         (insert "\n"))
  1202.         (let ( (start (point))
  1203.            (file-list (directory-files directory nil nil)) )
  1204.           (while file-list
  1205.         (let ( (fname (car file-list)) )
  1206.           (insert "  "
  1207.               prefix
  1208.               fname
  1209.               (if (and direx-indicate-directories
  1210.                    (file-directory-p fname))
  1211.                   "%"
  1212.                 "")
  1213.               "\n")
  1214.           (setq file-list (cdr file-list))))
  1215.           (if (or ls-done direx-use-long-directory)
  1216.           (let ( (ls-done nil) )
  1217.             (direx-fake-ls start (1- (point))))))
  1218.         (delete-blank-lines) ))))
  1219.  
  1220.  
  1221. (defun direx-add-entry (directory name)
  1222.   "  Add an entry for file name if it is in a subdirectory of the
  1223.   defualt directory. This will fail if directory is made up of links.
  1224.   Right now, we are so lazy that we do not bother to sort."
  1225.     (if (= 0 (string-match (expand-file-name default-directory)
  1226.               (expand-file-name directory)))
  1227.       (let ( (buffer-read-only nil)
  1228.          (relative-directory
  1229.           (substring directory (match-end 0) (length directory)))
  1230.          (ls-was-done ls-done)
  1231.          (ls-done nil)
  1232.          (start (point)) )
  1233.     (if (not (= (point) (point-min)))
  1234.         (insert "\n"))
  1235.     (insert "  " relative-directory name)
  1236.     (if ls-was-done
  1237.         (direx-fake-ls start (point)))
  1238.     (direx-before-file-name))))
  1239.  
  1240.  
  1241.  
  1242. (defun direx-move-to-file-name ()
  1243.   "Move to the file name field in a direx buffer."
  1244.   (end-of-line))
  1245.  
  1246. (defun direx-before-file-name ()
  1247.   "Move the point before a file name."
  1248.   (direx-move-to-file-name)
  1249.   (skip-chars-backward "^ \n\t"))
  1250.  
  1251. (defun direx-file-name ()
  1252.   "Return the name of the file on this line."
  1253.   (save-excursion
  1254.     (direx-move-to-file-name)
  1255.     (let ( (name (name-around-point)) )
  1256.       (if (string= name "")
  1257.       (error "No file on this line.")
  1258.     name))))
  1259.  
  1260. (defun direx-expand-subdirectory ()
  1261.   "Insert the subdirectory for the current file in a direx buffer."
  1262.   (interactive)
  1263.   (direx-move-to-file-name)
  1264.   (let ( (buffer-read-only nil)
  1265.      (name  (direx-file-name))
  1266.       (start (point)) )
  1267.     (end-of-line 1)
  1268.     (direx-show-directory-fast
  1269.      (file-name-as-directory
  1270.       (concat default-directory name)))
  1271.     (goto-char start)
  1272.     (direx-next-line)))
  1273.  
  1274. (if (vms-p)
  1275.     (progn
  1276.       (defun vms-remove-colon (name)
  1277.     (if (string= ":" (substring name -1))
  1278.         (substring name 0 -1)
  1279.       name))
  1280.  
  1281.       (defun vms-remove-000000 (name)
  1282.     (let ((start-zeros (string-match "000000\\." name)))
  1283.       (if start-zeros
  1284.           (concat (substring name 0 start-zeros)
  1285.               (substring name (+ start-zeros 7)))
  1286.         name)))
  1287.  
  1288.       (defun vms-eval-logical (name)
  1289.     (let* ((upname  (upcase name))
  1290.            (nocolon (vms-remove-colon upname))
  1291.            (translation (getenv nocolon)))
  1292.       (if translation
  1293.           (vms-eval-logical translation)
  1294.         (vms-remove-000000 upname))))))
  1295.  
  1296. (defun direx (directory)
  1297.   "Make a buffer for directory and direx in it."
  1298.   (interactive "DDirectory: ")
  1299.   (let* ( (ex-name (file-name-as-directory (expand-file-name directory)))
  1300.       (dir     (if (vms-p) (vms-eval-logical ex-name) ex-name))
  1301.       (buffer  (get-buffer-create dir)) )
  1302.     (switch-to-buffer buffer)
  1303.     (let ( (buffer-read-only nil) )
  1304.       (erase-buffer)
  1305.       (setq buffer-read-only t)
  1306.       (setq default-directory dir)
  1307.       (make-local-variable 'ls-done)
  1308.       (setq ls-done nil)
  1309.       (direx-show-directory-fast default-directory)
  1310.       (goto-char (point-min))
  1311.       (direx-before-file-name)
  1312.       (direx-mode dir)
  1313.       (set-buffer-modified-p nil))
  1314.     (setq buffer-read-only t)))
  1315.  
  1316.  
  1317. (defun direx-file (file)
  1318.   "Find the file FILE unless it is a directory.  If it is a directory,
  1319.    direx it."
  1320.   (interactive "FFile: ")
  1321.   (let ( (attributes (file-attributes file)) )
  1322.     (cond ( (eq (car attributes) t)
  1323.         (direx (expand-file-name file)) )
  1324.       ( (car attributes)
  1325.         (direx-file (car attributes)) )
  1326.       ( t
  1327.         (find-file file) ))))
  1328.       
  1329. (defun direx-alternate-file (file)
  1330.   "Visit the file FILE unless it is a directory.  If it is a directory,
  1331.    direx it. Kills the current buffer."
  1332.   (interactive "FFile: ")
  1333.   (let ( (attributes (file-attributes file))
  1334.      (full-name (expand-file-name file)) )
  1335.     (cond ( (eq (car attributes) t)
  1336.         (kill-buffer (current-buffer)) 
  1337.         (direx full-name) )
  1338.       ( (car attributes)
  1339.         (direx-alternate-file (car attributes)) )
  1340.       ( t (find-alternate-file file) ))))
  1341.  
  1342.  
  1343.  
  1344. (if (vms-p)
  1345.     (defun uid-to-uname (uid) uid)
  1346.   (progn
  1347.     (defvar uid-cache '(("-1"."paranoid"))
  1348.       "  A cache for argument-value pairs from uid-to-uname.")
  1349.  
  1350.     (defun password-buffer ()
  1351.       "Return the buffer *passwd* which hopefully contains the passwd file."
  1352.       (or (get-buffer "*passwd*")
  1353.       (save-excursion
  1354.         (switch-to-buffer (get-buffer-create "*passwd*"))
  1355.         (insert-file "/etc/passwd")
  1356.         (current-buffer))))
  1357.  
  1358.  
  1359.     (defun uid-to-uname (uid)
  1360.       "  Convert a user id to a user name.  We assume we can lay claim to a
  1361. buffer named *passwd*."
  1362.       (or (cdr (assoc uid uid-cache))
  1363.       (let ( (pwbuff (password-buffer)) )
  1364.         (save-excursion
  1365.           (switch-to-buffer pwbuff)
  1366.           (goto-char (point-min))
  1367.           (let* ((uid-string (concat ":" uid ":"))
  1368.              (pwstring (format "^\\([^:\n]*\\):[^:\n]*%s" uid-string)))
  1369.         (catch 'no-such-uid
  1370.           (while (not (looking-at pwstring))
  1371.             (if (not (search-forward uid-string nil t))
  1372.             (throw 'no-such-uid uid))
  1373.             (beginning-of-line))
  1374.           (let ((uname
  1375.              (buffer-substring (match-beginning 1) (match-end 1))))
  1376.             (setq uid-cache (cons (cons uid uname) uid-cache))
  1377.             (bury-buffer (current-buffer))
  1378.             uname)))))))))
  1379.  
  1380. (defun direx-fake-ls (&optional start end)
  1381.   "  The current buffer should consist of lines of file names.
  1382.    direx-fake-ls makes it look like they were put there by ls -l.
  1383.    Optional parameters START and END bound the action of direx-fake-ls"
  1384.   (interactive)
  1385.   (if ls-done
  1386.       nil
  1387.     (save-excursion
  1388.       (let ( (buffer-read-only nil)
  1389.          (bottom (or end (point-max)))
  1390.          (top (or start (point-min))) )
  1391.     (goto-char (1- bottom))
  1392.     (while (>= (point) top)
  1393.       (let ( (attributes
  1394.           (or (file-attributes (direx-file-name))
  1395.               '(() -1 -1 () () () () "???" "-barf!-"))) )
  1396.         (beginning-of-line)
  1397.         (if (= (point) top) (setq top (point-max)))
  1398.         (direx-before-file-name)
  1399.         (let ( (access (nth 8 attributes))
  1400.            (links  (concat (nth 1 attributes)))
  1401.            (uid    (concat (nth 2 attributes)))
  1402.            (date   (nth 5 attributes))
  1403.            (size   (concat (nth 7 attributes))) )
  1404.           (insert access)
  1405.           (indent-to-column (- 20 (length links)))
  1406.           (if (vms-p)
  1407.           (progn (insert (time-string date)) (backward-delete-char 1))
  1408.         (insert links " " (uid-to-uname uid)))
  1409.           (indent-to-column (- 50 (length size)))
  1410.           (insert size "  ")
  1411.           (direx-previous-line))))
  1412.     (setq ls-done t)))
  1413.     (direx-before-file-name)))
  1414.  
  1415. (defun direx-next-line (&optional count)
  1416.   "Move to the file name on the next line.  With ARG, move that many lines."
  1417.   (interactive "p")
  1418.   (let ( (n (or count 1)) )
  1419.     (forward-line n)
  1420.     (direx-before-file-name)))
  1421.  
  1422. (defun direx-previous-line (&optional count)
  1423.   "Move to the file name on the previous line. 
  1424.    With ARG, move that many lines."
  1425.   (interactive "p")
  1426.   (let ( (n (or count 1)) )
  1427.     (direx-next-line (- n))))
  1428.  
  1429. (defun direx-set-deletion-field (value)
  1430.   "Put the char VALUE in the deletion field of the current line.
  1431.    Signal an error if there is no file on this line.
  1432.    Do nothing if the file on this line is a directory."
  1433.   (let* ( (name (direx-file-name))
  1434.       (buffer-read-only nil)
  1435.       (attributes (file-attributes name)) )
  1436.     (or (eq (car attributes) t)
  1437.       (progn
  1438.     (beginning-of-line 1)
  1439.     (delete-char 1)
  1440.     (insert value)
  1441.     (direx-before-file-name)))))
  1442.  
  1443.  
  1444. (defun direx-flag-file-deleted (&optional count)
  1445.   "Mark a file for deletion."
  1446.   (interactive "p")
  1447.   (repeat count
  1448.       '(progn
  1449.          (direx-set-deletion-field "D")
  1450.          (direx-next-line))))
  1451.  
  1452. (defun direx-unflag (&optional count)
  1453.   "Unmark a bunch of files."
  1454.   (interactive "p")
  1455.   (repeat count
  1456.       '(progn
  1457.          (direx-set-deletion-field " ")
  1458.          (direx-next-line))))
  1459.  
  1460. (defun direx-backup-unflag (&optional count)
  1461.   "Unmark a bunch of files moving backwards."
  1462.   (interactive "p")
  1463.   (repeat count
  1464.       '(progn
  1465.          (direx-previous-line)
  1466.          (direx-set-deletion-field " "))))
  1467.  
  1468. (defun direx-file-marked-p ()
  1469.   "Return t if the current line has a deletion mark."
  1470.   (save-excursion
  1471.     (beginning-of-line 1)
  1472.     (looking-at "D ")))
  1473.  
  1474. (defun direx-revert (&optional arg noconfirm)
  1475.   "Revert a direx buffer."
  1476.   (interactive)
  1477.   (let ( (buffer-read-only nil) )
  1478.     (erase-buffer)
  1479.     (direx-show-directory-fast default-directory)
  1480.     (beginning-of-buffer)
  1481.     (direx-before-file-name)))
  1482.  
  1483.  
  1484. (defun direx-file-other-window (file)
  1485.   "Direx FILE in another window."
  1486.   (interactive "FFile:")
  1487.   (let ( (expanded-name (expand-file-name file)) )
  1488.     (other-window 1)
  1489.     (direx-file expanded-name)))
  1490.  
  1491.  
  1492. (defun direx-view-file (file)
  1493.   "Find FILE in view mode.  If FILE is a directory, direx it instead."
  1494.   (interactive "fFile: ")
  1495.   (let ( (attributes (file-attributes file)) )
  1496.     (cond ( (eq (car attributes) t)
  1497.         (direx (expand-file-name file)) )
  1498.       ( (car attributes)
  1499.         (direx-view-file (car-attributes)) )
  1500.       ( t
  1501.         (view-file file) ))))
  1502.  
  1503.  
  1504. (defun direx-find-this ()
  1505.   "Direx interaction for direx-file."
  1506.   (interactive)
  1507.   (direx-file (direx-file-name)))
  1508.  
  1509. (defun direx-alternate-this ()
  1510.   "Direx interaction for direx-alternate-file."
  1511.   (interactive)
  1512.   (direx-alternate-file (direx-file-name)))
  1513.  
  1514. (defun direx-view-this ()
  1515.   "Direx interaction for direx-view-file."
  1516.   (interactive)
  1517.   (direx-view-file (direx-file-name)))
  1518.  
  1519. (defun direx-this-other-window ()
  1520.   "Direx interaction for direx-file-other-window."
  1521.   (interactive)
  1522.   (direx-file-other-window (direx-file-name)))
  1523.  
  1524. (defun direx-rename-file (to-file)
  1525.   "Rename this file to TO-FILE."
  1526.   (interactive "FRename to: ")
  1527.   (setq to-file (expand-file-name to-file))
  1528.   (rename-file (expand-file-name (direx-file-name)) to-file)
  1529.   (let ((buffer-read-only nil))
  1530.     (beginning-of-line)
  1531.     (delete-region (point) (progn (forward-line 1) (point)))
  1532.     (end-of-line 0)
  1533.     (setq to-file (expand-file-name to-file))
  1534.     (direx-add-entry (file-name-directory to-file)
  1535.              (file-name-nondirectory to-file))))
  1536.  
  1537.   
  1538. (defun direx-do-deletions ()
  1539.   "In direx, delete the files flagged for deletion."
  1540.   (interactive)
  1541.   (let (delete-list answer)
  1542.     (save-excursion
  1543.      (goto-char 1)
  1544.      (while (re-search-forward "^D" nil t)
  1545.        (setq delete-list
  1546.          (cons (cons (direx-file-name) (1- (point)))
  1547.            delete-list))))
  1548.     (if (null delete-list)
  1549.     (message "(No deletions requested)")
  1550.       (save-window-excursion
  1551.        (switch-to-buffer " *Deletions*")
  1552.        (erase-buffer)
  1553.        (setq fill-column (- (window-width) 10))
  1554.        (let ((l (reverse delete-list)))
  1555.          ;; Files should be in forward order for this loop.
  1556.      (while l
  1557.        (if (> (current-column) (- (window-width) 21))
  1558.            (insert ?\n)
  1559.          (or (bobp)
  1560.          (indent-to (* (/ (+ (current-column) 19) 20) 20) 1)))
  1561.        (insert (car (car l)))
  1562.        (setq l (cdr l))))
  1563.        (goto-char (point-min))
  1564.        (setq answer (yes-or-no-p "Delete these files? ")))
  1565.       (if answer
  1566.       (let ((l delete-list)
  1567.         failures)
  1568.         ;; Files better be in reverse order for this loop!
  1569.         ;; That way as changes are made in the buffer
  1570.         ;; they do not shift the lines still to be changed.
  1571.         (while l
  1572.           (goto-char (cdr (car l)))
  1573.           (let ((buffer-read-only nil))
  1574.         (condition-case ()
  1575.             (progn (delete-file (concat default-directory
  1576.                         (car (car l))))
  1577.                (message (concat default-directory (car (car l))))
  1578.                (delete-region (progn (beginning-of-line) (point))
  1579.                       (progn (forward-line 1) (point))))
  1580.           (error (delete-char 1)
  1581.              (insert " ")
  1582.              (setq failures (cons (car (car l)) failures)))))
  1583.           (setq l (cdr l)))
  1584.         (if failures
  1585.         (message "Deletions failed: %s"
  1586.              (prin1-to-string failures))
  1587.           (set-buffer-modified-p nil))
  1588.         (direx-before-file-name))))))
  1589.  
  1590.  
  1591. (defun direx-copy-file (to-file)
  1592.   "Copy this file to TO-FILE."
  1593.   (interactive "FCopy to: ")
  1594.   (copy-file (direx-file-name) to-file)
  1595.   (setq to-file (expand-file-name to-file))
  1596.   (end-of-line)
  1597.   (direx-add-entry (file-name-directory to-file)
  1598.            (file-name-nondirectory to-file)))
  1599.   
  1600.  
  1601. (defun direx-flag-auto-save-files ()
  1602.   "Flag for deletion files whose names suggest they are auto save files."
  1603.   (interactive)
  1604.   (save-excursion
  1605.    (let ((buffer-read-only nil))
  1606.      (goto-char (point-min))
  1607.      (while (not (eobp))
  1608.        (and (not (eolp))
  1609.         (if (fboundp 'auto-save-file-name-p)
  1610.         (let ((fn (direx-file-name)))
  1611.           (if fn (auto-save-file-name-p fn)))
  1612.           (if (direx-before-filename)
  1613.           (looking-at "#")))
  1614.         (direx-set-deletion-field "D"))
  1615.        (forward-line 1)))))
  1616.  
  1617.  
  1618. (defun direx-flag-backup-files ()
  1619.   "Flag all backup files (names ending with ~) for deletion."
  1620.   (interactive)
  1621.   (save-excursion
  1622.    (let ((buffer-read-only nil))
  1623.      (goto-char (point-min))
  1624.      (while (not (eobp))
  1625.        (and (not (eolp))
  1626.         (if (fboundp 'backup-file-name-p)
  1627.         (let ((fn (direx-file-name)))
  1628.           (if fn (backup-file-name-p fn)))
  1629.           (end-of-line)
  1630.           (forward-char -1)
  1631.           (looking-at "~"))
  1632.         (direx-set-deletion-field "D"))
  1633.        (forward-line 1)))))
  1634.  
  1635.  
  1636. (defconst direx-kept-versions 2
  1637.   "*When cleaning directory, number of versions to keep.")
  1638.  
  1639. (defun direx-clean-directory (keep)
  1640.   "  Flag numerical backups for Deletion.
  1641.   Spares dired-kept-versions latest versions, and kept-old-versions oldest.
  1642.   Positive numeric arg overrides dired-kept-versions;
  1643.   negative numeric arg overrides kept-old-versions with minus the arg."
  1644.   (interactive "P")
  1645.   (setq keep (if keep (prefix-numeric-value keep) direx-kept-versions))
  1646.   (let ((early-retention (if (< keep 0) (- keep) kept-old-versions))
  1647.     (late-retention (if (<= keep 0) direx-kept-versions keep))
  1648.     (file-version-assoc-list ()))
  1649.     ;; Look at each file.
  1650.     ;; If the file has numeric backup versions,
  1651.     ;; put on file-version-assoc-list an element of the form
  1652.     ;; (FILENAME . VERSION-NUMBER-LIST)
  1653.     (direx-map-direx-file-lines 'direx-collect-file-versions)
  1654.     ;; Sort each VERSION-NUMBER-LIST,
  1655.     ;; and remove the versions not to be deleted.
  1656.     (let ((fval file-version-assoc-list))
  1657.       (while fval
  1658.     (let* ((sorted-v-list (cons 'q (sort (cdr (car fval)) '<)))
  1659.            (v-count (length sorted-v-list)))
  1660.       (if (> v-count (+ early-retention late-retention))
  1661.           (rplacd (nthcdr early-retention sorted-v-list)
  1662.               (nthcdr (- v-count late-retention)
  1663.                   sorted-v-list)))
  1664.       (rplacd (car fval)
  1665.           (cdr sorted-v-list)))
  1666.     (setq fval (cdr fval)))) 
  1667.     ;; Look at each file.  If it is a numeric backup file,
  1668.     ;; find it in a VERSION-NUMBER-LIST and maybe flag it for deletion.
  1669.     (direx-map-direx-file-lines 'direx-trample-file-versions)))
  1670.  
  1671.  
  1672.  
  1673. (defun direx-collect-file-versions (ignore fn)
  1674.   "If it looks like fn has versions, we make a list of the versions.
  1675. We may want to flag some for deletion."
  1676.     (let* ((base-versions
  1677.         (concat (file-name-nondirectory fn) ".~"))
  1678.        (bv-length (length base-versions))
  1679.        (possibilities (file-name-all-completions
  1680.                base-versions
  1681.                (file-name-directory fn)))
  1682.        (versions (mapcar 'backup-extract-version possibilities)))
  1683.       (if versions
  1684.       (setq file-version-assoc-list (cons (cons fn versions)
  1685.                           file-version-assoc-list)))))
  1686.  
  1687. (defun direx-trample-file-versions (ignore fn)
  1688.   (let* ((start-vn (string-match "\\.~[0-9]+~$" fn))
  1689.      base-version-list)
  1690.     (and start-vn
  1691.      (setq base-version-list    ; there was a base version to which 
  1692.            (assoc (substring fn 0 start-vn)    ; this looks like a 
  1693.               file-version-assoc-list))    ; subversion
  1694.      (not (memq (string-to-int (substring fn (+ 2 start-vn)))
  1695.             base-version-list))    ; this one doesn't make the cut
  1696.      (direx-set-deletion-field "D"))))
  1697.  
  1698.  
  1699.  
  1700. (defun direx-map-direx-file-lines (fn)
  1701.   "perform fn with point at the end of each non-directory line:
  1702. arguments are the short and long filename"
  1703.   (save-excursion
  1704.     (let (filename longfilename (buffer-read-only nil))
  1705.       (goto-char (point-min))
  1706.       (while (not (eobp))
  1707.     (save-excursion
  1708.       (and (not (looking-at "  d"))
  1709.            (not (eolp))
  1710.            (setq filename (direx-file-name)
  1711.              longfilename (expand-file-name (direx-file-name)))
  1712.            (progn (end-of-line)
  1713.               (funcall fn filename longfilename))))
  1714.     (forward-line 1)))))
  1715.  
  1716.  
  1717.  
  1718. (defun direx-summary ()
  1719.   "Give the luser a summary of direx commands."
  1720.   (interactive)
  1721.   (message
  1722.    (substitute-command-keys
  1723.     "\\[direx-flag-file-deleted] delete, \\[direx-unflag] undelete, \\[direx-do-deletions] execute, \\[direx-find-this] find, \\[direx-alternate-this] jump")))
  1724.  
  1725.  
  1726.  
  1727. (defvar direx-mode-map nil "Local keymap for direx-mode buffers.")
  1728. (if direx-mode-map
  1729.     nil
  1730.   (setq direx-mode-map (make-keymap))
  1731.   (suppress-keymap direx-mode-map)
  1732.   (define-key direx-mode-map " "  'direx-next-line)
  1733.   (define-key direx-mode-map "#" 'direx-flag-auto-save-files)
  1734.   (define-key direx-mode-map "." 'direx-clean-directory)
  1735.   (define-key direx-mode-map "?" 'direx-summary)
  1736.   (define-key direx-mode-map "\C-?" 'direx-backup-unflag)
  1737.   (define-key direx-mode-map "\C-d" 'direx-flag-file-deleted)
  1738.   (define-key direx-mode-map "\C-n" 'direx-next-line)
  1739.   (define-key direx-mode-map "\C-p" 'direx-previous-line)
  1740.   (define-key direx-mode-map "c" 'direx-copy-file)
  1741.   (define-key direx-mode-map "d" 'direx-flag-file-deleted)
  1742.   (define-key direx-mode-map "e" 'direx-find-this)
  1743.   (define-key direx-mode-map "f" 'direx-find-this)
  1744.   (define-key direx-mode-map "g" 'revert-buffer)
  1745.   (define-key direx-mode-map "h" 'describe-mode)
  1746.   (define-key direx-mode-map "j" 'direx-alternate-this)
  1747.   (define-key direx-mode-map "l" 'direx-fake-ls)
  1748.   (define-key direx-mode-map "n" 'direx-next-line)
  1749.   (define-key direx-mode-map "o" 'direx-this-other-window)
  1750.   (define-key direx-mode-map "p" 'direx-previous-line)
  1751.   (define-key direx-mode-map "r" 'direx-rename-file)
  1752.   (define-key direx-mode-map "s" 'direx-expand-subdirectory)
  1753.   (define-key direx-mode-map "u" 'direx-unflag)
  1754.   (define-key direx-mode-map "v" 'direx-view-this)
  1755.   (define-key direx-mode-map "x" 'direx-do-deletions)
  1756.   (define-key direx-mode-map "~" 'direx-flag-backup-files))
  1757.  
  1758. ;; Direx mode is suitable only for specially formatted data.
  1759. (put 'direx-mode 'mode-class 'special)
  1760.  
  1761. (defun direx-mode (dirname)
  1762.   "Mode for \"editing\" directory listings.
  1763. In direx, you are \"editing\" a list of the files in a directory.
  1764. You can move using the usual cursor motion commands.
  1765. Letters no longer insert themselves.
  1766. Instead, type d to flag a file for Deletion.
  1767. Type u to Unflag a file (remove its D flag).
  1768.   Type Rubout to back up one line and unflag.
  1769. Type x to eXecute the deletions requested.
  1770. Type l to get a more informative directory listing.
  1771. Type f to Find the current line's file
  1772.   (or Direx it, if it is a directory).
  1773. Type o to find file or direx directory in Other window.
  1774. Type # to flag temporary files (names beginning with #) for Deletion.
  1775. Type ~ to flag backup files (names ending with ~) for Deletion.
  1776. Type . to flag numerical backups for Deletion.
  1777.   (Spares direx-kept-versions or its numeric argument.)
  1778. Type r to rename a file.
  1779. Type c to copy a file.
  1780. Type v to view a file in View mode, returning to Direx when done.
  1781. Type g to read the directory again.  This discards all deletion-flags.
  1782. Type j to direx-find this file in a buffer replacing the current buffer.
  1783. Type s to expand a subdirectory in place.
  1784. Type l to get a long directory listing for the files in the current buffer.
  1785. Space and Rubout can be used to move down and up by lines.
  1786. \\{direx-mode-map}"
  1787.   (kill-all-local-variables)    
  1788.   (make-local-variable 'revert-buffer-function)
  1789.   (setq revert-buffer-function 'direx-revert)
  1790.   (setq major-mode 'direx-mode)
  1791.   (setq mode-name "Direx")
  1792.   (make-local-variable 'ls-done)
  1793.   (setq default-directory dirname)
  1794.   (setq mode-line-buffer-identification '("Direx: %17b"))
  1795.   (setq case-fold-search (vms-p))
  1796.   (setq buffer-read-only t)
  1797.   (use-local-map direx-mode-map)
  1798.   (run-hooks 'direx-mode-hook))
  1799. -------------------------end of lisp/direx.el---------------------------
  1800.  
  1801. -- 
  1802. Mike Wexler(wyse!mikew)    Phone: (408)433-1000 x1330
  1803. Moderator of comp.sources.x
  1804.